1 =============================================================================
2 DYNAMIC LINK LIBRARY : CppShellExtThumbnailHandler Project Overview
3 =============================================================================
5 /////////////////////////////////////////////////////////////////////////////
8 The code sample demonstrates the C++ implementation of a thumbnail handler
9 for a new file type registered with the .recipe extension.
11 A thumbnail image handler provides an image to represent the item. It lets
12 you customize the thumbnail of files with a specific file extension. Windows
13 Vista and newer operating systems make greater use of file-specific thumbnail
14 images than earlier versions of Windows. Thumbnails of 32-bit resolution and
15 as large as 256x256 pixels are often used. File format owners should be
16 prepared to display their thumbnails at that size.
18 The example thumbnail handler has the class ID (CLSID):
19 {4D2FBA8D-621B-4447-AF6D-5794F479C4A5}
21 The handler implements the IInitializeWithStream and IThumbnailProvider
22 interfaces, and provides thumbnails for .recipe files. The .recipe file type
23 is simply an XML file registered as a unique file name extension. It includes
24 an element called "Picture", embedding an image file. The thumbnail handler
25 extracts the embedded image and asks the Shell to display it as a thumbnail.
28 /////////////////////////////////////////////////////////////////////////////
31 The example thumbnail handler must be registered on Windows Vista or newer
35 /////////////////////////////////////////////////////////////////////////////
40 If you are going to use the Shell extension in a x64 Windows system, please
41 configure the Visual C++ project to target 64-bit platforms using project
42 configurations (http://msdn.microsoft.com/en-us/library/9yb4317s.aspx).
44 If the extension is to be loaded in a 32-bit Windows system, you can use the
45 default Win32 project configuration to build the project.
47 In a command prompt running as administrator, navigate to the folder that
48 contains the build result CppShellExtThumbnailHandler.dll and enter the
51 Regsvr32.exe CppShellExtThumbnailHandler.dll
53 The thumbnail handler is registered successfully if you see a message box
56 "DllRegisterServer in CppShellExtThumbnailHandler.dll succeeded."
60 In a command prompt running as administrator, navigate to the folder that
61 contains the build result CppShellExtThumbnailHandler.dll and enter the
64 Regsvr32.exe /u CppShellExtThumbnailHandler.dll
66 The thumbnail handler is unregistered successfully if you see a message box
69 "DllUnregisterServer in CppShellExtThumbnailHandler.dll succeeded."
72 /////////////////////////////////////////////////////////////////////////////
75 The following steps walk through a demonstration of the thumbnail handler
78 Step1. If you are going to use the Shell extension in a x64 Windows system,
79 please configure the Visual C++ project to target 64-bit platforms using
80 project configurations (http://msdn.microsoft.com/en-us/library/9yb4317s.aspx).
81 If the extension is to be loaded in a 32-bit Windows system, you can use the
82 default Win32 project configuration.
84 Step2. After you successfully build the sample project in Visual Studio 2010,
85 you will get a DLL: CppShellExtThumbnailHandler.dll. Start a command prompt
86 as administrator, navigate to the folder that contains the file and enter the
89 Regsvr32.exe CppShellExtThumbnailHandler.dll
91 The thumbnail handler is registered successfully if you see a message box
94 "DllRegisterServer in CppShellExtThumbnailHandler.dll succeeded."
96 Step3. Find the chocolatechipcookies.recipe file in the sample folder. You
97 will see a picture of chocoate chip cookies as its thumbnail.
99 The .recipe file type is simply an XML file registered as a unique file name
100 extension. It includes an element called "Picture", embedding an image file.
101 The thumbnail handler extracts the embedded image and asks the Shell to
102 display it as a thumbnail.
104 Step4. In the same command prompt, run the command
106 Regsvr32.exe /u CppShellExtThumbnailHandler.dll
108 to unregister the Shell thumbnail handler.
111 /////////////////////////////////////////////////////////////////////////////
114 A. Creating and configuring the project
116 In Visual Studio 2010, create a Visual C++ / Win32 / Win32 Project named
117 "CppShellExtThumbnailHandler". In the "Application Settings" page of Win32
118 Application Wizard, select the application type as "DLL" and check the "Empty
119 project" option. After you click the Finish button, an empty Win32 DLL
122 -----------------------------------------------------------------------------
124 B. Implementing a basic Component Object Model (COM) DLL
126 Shell extension handlers are COM objects implemented as DLLs. Making a basic
127 COM includes implementing DllGetClassObject, DllCanUnloadNow,
128 DllRegisterServer, and DllUnregisterServer in (and exporting them from) the
129 DLL, adding a COM class with the basic implementation of the IUnknown
130 interface, preparing the class factory for your COM class. The relevant files
131 in this code sample are:
133 dllmain.cpp - implements DllMain and the DllGetClassObject, DllCanUnloadNow,
134 DllRegisterServer, DllUnregisterServer functions that are necessary for a
137 GlobalExportFunctions.def - exports the DllGetClassObject, DllCanUnloadNow,
138 DllRegisterServer, DllUnregisterServer functions from the DLL through the
139 module-definition file. You need to pass the .def file to the linker by
140 configuring the Module Definition File property in the project's Property
141 Pages / Linker / Input property page.
143 Reg.h/cpp - defines the reusable helper functions to register or unregister
144 in-process COM components in the registry:
145 RegisterInprocServer, UnregisterInprocServer
147 RecipeThumbnailProvider.h/cpp - defines the COM class. You can find the basic
148 implementation of the IUnknown interface in the files.
150 ClassFactory.h/cpp - defines the class factory for the COM class.
152 -----------------------------------------------------------------------------
154 C. Implementing the thumbnail handler and registering it for a certain file
158 Implementing the thumbnail handler:
160 The RecipeThumbnailProvider.h/cpp files define a thumbnail provider. It
161 implements the IInitializeWithStream and IThumbnailProvider interfaces, and
162 provides thumbnails for .recipe files.
164 class RecipeThumbnailProvider :
165 public IInitializeWithStream,
166 public IThumbnailProvider
169 // IInitializeWithStream
170 IFACEMETHODIMP Initialize(IStream *pStream, DWORD grfMode);
172 // IThumbnailProvider
173 IFACEMETHODIMP GetThumbnail(UINT cx, HBITMAP *phbmp, WTS_ALPHATYPE *pdwAlpha);
176 1. Implementing IThumbnailProvider
178 The IThumbnailProvider interface has been introduced in Windows Vista to
179 make providing a thumbnail easier and more straightforward than in the past,
180 when IExtractImage would have been used instead. Note, that existing code
181 that uses IExtractImage is still valid under Windows Vista. However,
182 IExtractImage is not supported in the Details pane.
184 IThumbnailProvider has only one method¡ªGetThumbnail¡ªthat is called with the
185 largest desired size of the image, in pixels. Although the parameter is
186 called cx, this is used as the maximum size of both the x and y dimensions.
187 If the retrieved thumbnail is not square, then the longer axis is limited
188 by cx and the aspect ratio of the original image respected.
190 On exit, GetThumbnail provides a handle to the retrieved image. It also
191 provides a value that indicates the color format of the image and whether
192 it has valid alpha information.
194 IFACEMETHODIMP RecipeThumbnailProvider::GetThumbnail(UINT cx, HBITMAP *phbmp,
195 WTS_ALPHATYPE *pdwAlpha)
197 // Load the XML document.
198 IXMLDOMDocument *pXMLDoc = NULL;
199 HRESULT hr = LoadXMLDocument(&pXMLDoc);
202 // Read the preview image from the XML document.
203 hr = GetRecipeImage(pXMLDoc, cx, phbmp, pdwAlpha);
209 The .recipe file type is simply an XML file registered as a unique file
210 name extension. It includes an element called Picture that embeds images
211 to be used as the thumbnail for this particular .recipe file. The XML
212 may provide images of different sizes, and the code can query image
213 matching the desired size specified by the cx parameter of GetThumbnail.
214 For simplicity, this sample omits the cx paramter and provides only one
215 image for all situations.
217 2. Implementing IInitializeWithStream/IInitializeWithItem/IInitializeWithFile
219 IThumbnailProvider must always be implemented in concert with one of these
222 IInitializeWithStream - provides the file stream
223 IInitializeWithItem - provides the IShellItem
224 IInitializeWithFile - provides the file path
226 Whenever possible, it is recommended that initialization be done through a
227 stream using IInitializeWithStream. Benefits of this include increased
228 security and stability.
232 IFACEMETHODIMP RecipeThumbnailProvider::Initialize(IStream *pStream, DWORD grfMode)
234 // A handler instance should be initialized only once in its lifetime.
235 HRESULT hr = HRESULT_FROM_WIN32(ERROR_ALREADY_INITIALIZED);
236 if (m_pStream == NULL)
238 // Take a reference to the stream if it has not been initialized yet.
239 hr = pStream->QueryInterface(&m_pStream);
245 Registering the handler for a certain file class:
247 The CLSID of the handler is declared at the beginning of dllmain.cpp.
249 // {4D2FBA8D-621B-4447-AF6D-5794F479C4A5}
250 const CLSID CLSID_RecipeThumbnailProvider =
251 { 0x4D2FBA8D, 0x621B, 0x4447, { 0xAF, 0x6D, 0x57, 0x94, 0xF4, 0x79, 0xC4, 0xA5 } };
253 When you write your own handler, you must create a new CLSID by using the
254 "Create GUID" tool in the Tools menu, and specify the CLSID value here.
256 Thumbnail handlers can be associated with a file class. The handlers are
257 registered by setting the default value of the following registry key to be
258 the CLSID the handler class.
260 HKEY_CLASSES_ROOT\<File Type>\shellex\{e357fccd-a995-4576-b01f-234630154e96}
262 The registration of the thumbnail handler is implemented in the
263 DllRegisterServer function of dllmain.cpp. DllRegisterServer first calls the
264 RegisterInprocServer function in Reg.h/cpp to register the COM component.
265 Next, it calls RegisterShellExtThumbnailHandler to associate the handler
266 with a certain file type. If the file type starts with '.', it tries to read
267 the default value of the HKCR\<File Type> key which may contain the Program
268 ID to which the file type is linked. If the default value is not empty, use
269 the Program ID as the file type to proceed the registration.
271 For example, this code sample associates the handler with '.recipe' files.
272 The following keys and values are added in the registration process of the
279 ForceRemove {4D2FBA8D-621B-4447-AF6D-5794F479C4A5} =
280 s 'CppShellExtThumbnailHandler.RecipeThumbnailProvider Class'
282 InprocServer32 = s '<Path of CppShellExtThumbnailHandler.DLL file>'
284 val ThreadingModel = s 'Apartment'
292 {e357fccd-a995-4576-b01f-234630154e96} =
293 s '{4D2FBA8D-621B-4447-AF6D-5794F479C4A5}'
298 The unregistration is implemented in the DllUnregisterServer function of
299 dllmain.cpp. It removes the HKCR\CLSID\{<CLSID>} key and the
300 HKCR\<File Type>\shellex\{e357fccd-a995-4576-b01f-234630154e96} key.
303 /////////////////////////////////////////////////////////////////////////////
306 Debugging thumbnail handlers is difficult for several reasons.
308 1) The Windows Explorer hosts thumbnail providers in an isolated process to
309 get robustness and improve security. Because of this it is difficult to debug
310 your handler as you cannot set breakpoints on your code in the explorer.exe
311 process as it is not loaded there. The isolated process is DllHost.exe and
312 this is used for other purposes so finding the right instance of this process
315 2) Once a thumbnail is computed for a particular file it is cached and your
316 handler won't be called again for that item unless you invalidate the cache
317 by updating the modification date of the file. Note that this cache works
318 even if the files are renamed or moved.
320 Given all of these issues the easiest way to debug your code in a test
321 application then once you have proven it works there test it in the context
324 Another thing to do is to disable the process isolation feature of explorer.
325 You can do this by putting the following named value on the CLSID of your
328 HKCR\CLSID\{CLSID of Your Handler}
329 DisableProcessIsolation=REG_DWORD:1
331 Be sure to not ship your handler with this on as customers require the
332 security and robustness benefits of the isolated process feature.
335 /////////////////////////////////////////////////////////////////////////////
338 MSDN: Thumbnail Handlers
339 http://msdn.microsoft.com/en-us/library/cc144118.aspx
341 MSDN: Building Thumbnail Handlers
342 http://msdn.microsoft.com/en-us/library/cc144114.aspx
344 MSDN: Thumbnail Handler Guidelines
345 http://msdn.microsoft.com/en-us/library/cc144115.aspx
347 MSDN: IThumbnailProvider Interface
348 http://msdn.microsoft.com/en-us/library/bb774614.aspx
351 /////////////////////////////////////////////////////////////////////////////